﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YArchitech.Revit;
using YJKArchUtils.Utils;
using YJKRevitBase.WinForm;
using YJKRevitDimensionText.Forms;
using YJKRevitDimensionText.Jigs;
using YJKRevitDimensionText.Utility;
using YJKRevitView;

namespace YJKRevitDimensionText.Commands
{
	[Regeneration(RegenerationOption.Manual)]
	[Transaction(TransactionMode.Manual)]
	public class CmdLeaderDim : YJKCommandManual
	{
		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		protected override Result YJKExcute(ExternalCommandData cmdData, ref string message, ElementSet elements)
		{
            CmdViewType cmdViewType = (CmdViewType)111;
			if (SwitchView.SetUsableView(cmdViewType, cmdData) != Autodesk.Revit.UI.Result.Succeeded)
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			if (CmdLeaderDim._hWndRevit == null)
			{
                CmdLeaderDim._hWndRevit = new WindowHandle(Process.GetCurrentProcess().MainWindowHandle);
			}
			Autodesk.Revit.DB.View activeView = cmdData.Application.ActiveUIDocument.ActiveView;
			if (!Helper.ViewValidating(cmdData.Application.ActiveUIDocument.Document, activeView, ref message))
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			this.m_Revit = cmdData;
			this.InitDimData();
			DlgLeaderDim dlgLeaderDim = new DlgLeaderDim(this.m_Revit);
			dlgLeaderDim.Show(CmdLeaderDim._hWndRevit);
			int wMsg = 7;
			CmdLeaderDim.SendMessage(CmdLeaderDim._hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
			TextNote textNote = null;
			XYZ startPoint = null;
			XYZ endPoint = null;
			XYZ thirdPoint = null;
			for (;;)
			{
				CmdLeaderDim._FuncResultMode funcResultMode = this.LeaderDimJig(dlgLeaderDim, ref startPoint, ref endPoint, ref thirdPoint);
				if (funcResultMode == CmdLeaderDim._FuncResultMode.FRM_FALSE)
				{
					break;
				}
				if (funcResultMode != CmdLeaderDim._FuncResultMode.FRM_CONTINUE)
				{
					ElementSet elementSet = new ElementSet();
					if (this.CreateText(this.m_uiDoc.Document, startPoint, ref endPoint, ref thirdPoint, dlgLeaderDim, ref elementSet, ref textNote) == CmdLeaderDim._FuncResultMode.FRM_FALSE)
					{
						break;
					}
					this.CreateShareLeader(startPoint, endPoint, thirdPoint, dlgLeaderDim, ref elementSet, ref textNote);
					Transaction transaction = new Transaction(this.m_doc, "group");
					transaction.Start();
					RevitVersionFuncs.NewGroup(this.m_doc, elementSet).GroupType.Name = "引线标注";
					transaction.Commit();
				}
			}
			dlgLeaderDim.Close();
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private void InitDimData()
		{
			DimDate.FontFamily = AssistFunc.GetSystemFontTypeStringArray(this.m_doc);
			IEnumerable<Element> enumerable = new FilteredElementCollector(this.m_doc).OfClass(typeof(Autodesk.Revit.DB.ElementType)).ToElements();
			List<string> list = new List<string>();
			list.Add("无");
			foreach (Element element in enumerable)
			{
				Autodesk.Revit.DB.ElementType elementType = (Autodesk.Revit.DB.ElementType)element;
				if ((elementType.get_Parameter(BuiltInParameter.ALL_MODEL_FAMILY_NAME).AsString() == "箭头" || elementType.get_Parameter(BuiltInParameter.ALL_MODEL_FAMILY_NAME).AsString() == "Arrowhead") && elementType.Name != "Arrowhead" && elementType.Name != "箭头" && !list.Contains(elementType.Name))
				{
					list.Add(elementType.Name);
				}
			}
			DimDate.ArrowType = list;
		}

		private CmdLeaderDim._FuncResultMode LeaderDimJig(DlgLeaderDim ltf, ref XYZ ptStart, ref XYZ ptEnd, ref XYZ ptThird)
		{
			using (LeaderDimJig leaderDimJig = new LeaderDimJig(this.m_Revit.Application.ActiveUIDocument, ltf))
			{
				ptStart = leaderDimJig.PickStartPoint("请选择标记点:");
				if (ptStart == null)
				{
					return CmdLeaderDim._FuncResultMode.FRM_FALSE;
				}
				ptEnd = leaderDimJig.PickDimPoint(ptStart, "请选择标注位置：");
				if (ptEnd == null)
				{
					return CmdLeaderDim._FuncResultMode.FRM_FALSE;
				}
				if (ptEnd.DistanceTo(ptStart) < AssistFunc.mmToFeet(1.0))
				{
					YJKMessageBox.Show("两点不能太近！");
					return CmdLeaderDim._FuncResultMode.FRM_CONTINUE;
				}
				ptThird = leaderDimJig.PickTextPoint(ptStart, ptEnd, "请确定标注文字位置：");
				if (ptThird == null)
				{
					return CmdLeaderDim._FuncResultMode.FRM_FALSE;
				}
				if (ptThird.DistanceTo(ptEnd) < AssistFunc.mmToFeet(1.0))
				{
					YJKMessageBox.Show("两点不能太近！");
					return CmdLeaderDim._FuncResultMode.FRM_CONTINUE;
				}
			}
			return CmdLeaderDim._FuncResultMode.FRM_TRUE;
		}

		private CmdLeaderDim._FuncResultMode CreateText(Autodesk.Revit.DB.Document doc, XYZ startPoint, ref XYZ endPoint, ref XYZ thirdPoint, DlgLeaderDim ltf, ref ElementSet newgrpElements, ref TextNote proportionText)
		{
			Transaction transaction = new Transaction(this.m_doc);
			transaction.Start("thridpoint");
			try
			{
				Autodesk.Revit.DB.View activeView = this.m_doc.ActiveView;
                proportionText = RevitDocumentExtension.GetTextNode(this.m_doc, activeView, thirdPoint, activeView.RightDirection, activeView.UpDirection, 0.5, (Autodesk.Revit.DB.TextAlignFlags)64, (Autodesk.Revit.DB.TextNoteLeaderTypes)0, (TextNoteLeaderStyles)1, startPoint, endPoint, ".");
				newgrpElements.Insert(proportionText);
			}
			catch
			{
				transaction.RollBack();
				return CmdLeaderDim._FuncResultMode.FRM_FALSE;
			}
			Element selectType = Helper.GetSelectType<TextNoteType>(this.m_doc, ltf.fontType);
			TextNoteType textNoteType = selectType as TextNoteType;
			double num = textNoteType.get_Parameter(BuiltInParameter.TEXT_SIZE).AsDouble() * (double)this.m_doc.ActiveView.Scale;
			double num2 = textNoteType.get_Parameter(BuiltInParameter.TEXT_WIDTH_SCALE).AsDouble();
			double num3 = num * num2 / RevitDocumentExtension.GetVersionTextWidthFactory();
			XYZ ptBase = null;
			SpecialCharactorDrawingKit specialCharactorDrawingKit = new SpecialCharactorDrawingKit(this.m_Revit, ltf.fontType);
			SpecialCharactorDrawingKit.TextHorizontalAlignment hAlignment = SpecialCharactorDrawingKit.TextHorizontalAlignment.THA_LEFT;
			SpecialCharactorDrawingKit.TextVerticalAlignment vAlignment = SpecialCharactorDrawingKit.TextVerticalAlignment.TVA_TOP;
			List<string> list = SpecialCharactorDrawingKit.SplitString(ltf.LineUpText);
			list.Reverse();
			for (int i = 0; i < list.Count; i++)
			{
				double dTextWidth = (double)SpecialCharactorDrawingKit.GetLength(list[i]) * num3;
				double dOffsetY = num * 1.1 + num * (double)i * 1.4;
				this.CalculatTextPosition(ltf.alignStyle, dTextWidth, dOffsetY, endPoint, thirdPoint, ref ptBase, ref hAlignment);
				foreach (Element element in specialCharactorDrawingKit.DrawSingleRowCharactors1(ptBase, list[i], hAlignment, vAlignment))
				{
					newgrpElements.Insert(element);
				}
			}
			List<string> list2 = SpecialCharactorDrawingKit.SplitString(ltf.LineDownText);
			for (int j = 0; j < list2.Count; j++)
			{
				double dTextWidth2 = (double)SpecialCharactorDrawingKit.GetLength(list2[j]) * num3;
				double dOffsetY2 = -(num * 1.1 + num * (double)j * 1.4);
				this.CalculatTextPosition(ltf.alignStyle, dTextWidth2, dOffsetY2, endPoint, thirdPoint, ref ptBase, ref hAlignment);
				foreach (Element element2 in specialCharactorDrawingKit.DrawSingleRowCharactors1(ptBase, list2[j], hAlignment, vAlignment))
				{
					newgrpElements.Insert(element2);
				}
			}
			try
			{
				Element selectType2 = Helper.GetSelectType<Autodesk.Revit.DB.ElementType>(this.m_doc, ltf.arrowType);
				string text = "HY_Leader_";
				if (selectType2 == null || ltf.arrowType == "无")
				{
					text += "无标题";
				}
				else
				{
					text += selectType2.Name;
				}
				TextNoteType textNoteType2 = Helper.GetSelectType<TextNoteType>(this.m_doc, text) as TextNoteType;
				if (textNoteType2 == null)
				{
					textNoteType2 = ((selectType as TextNoteType).Duplicate(text) as TextNoteType);
					textNoteType2.get_Parameter(BuiltInParameter.TEXT_SIZE).Set(AssistFunc.mmToFeet(0.5));
					if (selectType2 == null || ltf.arrowType == "无")
					{
						textNoteType2.get_Parameter(BuiltInParameter.LEADER_ARROWHEAD).Set(ElementId.InvalidElementId);
					}
					else
					{
						textNoteType2.get_Parameter(BuiltInParameter.LEADER_ARROWHEAD).Set(selectType2.Id);
					}
					textNoteType2.get_Parameter(BuiltInParameter.TEXT_WIDTH_SCALE).Set(0.2);
				}
				proportionText.TextNoteType = textNoteType2;
				RevitElementExtension.SetTextNoteCoord(proportionText, endPoint);
				RevitElementExtension.GetMinimumAllowedWidth(this.m_doc, proportionText.GetTypeId());
				RevitElementExtension.SetTextNoteWidth(proportionText, AssistFunc.mmToFeet(0.5));
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
				return CmdLeaderDim._FuncResultMode.FRM_CONTINUE;
			}
			Transaction transaction2 = new Transaction(this.m_doc);
			transaction2.Start("revits");
			try
			{
				double num4 = proportionText.Height * (double)doc.ActiveView.Scale;
				new XYZ(endPoint.X, endPoint.Y - num4 / 2.0, endPoint.Z);
				new XYZ(thirdPoint.X, thirdPoint.Y - num4 / 2.0, thirdPoint.Z);
				DetailCurve detailCurve = doc.Create.NewDetailCurve(doc.ActiveView, Line.CreateBound(endPoint, thirdPoint));
				newgrpElements.Insert(detailCurve);
                RevitElementExtension.HyGetLeaders(proportionText).get_Item(0).Elbow = endPoint;
                RevitElementExtension.HyGetLeaders(proportionText).get_Item(0).End = startPoint;
				transaction2.Commit();
			}
			catch
			{
				transaction2.RollBack();
				return CmdLeaderDim._FuncResultMode.FRM_CONTINUE;
			}
			return CmdLeaderDim._FuncResultMode.FRM_TRUE;
		}

		private CmdLeaderDim._FuncResultMode CreateShareLeader(XYZ startPoint, XYZ endPoint, XYZ thirdPoint, DlgLeaderDim ltf, ref ElementSet newgrpElements, ref TextNote proportionText)
		{
			if (RevitElementExtension.HyGetLeaders(proportionText).Size != 1)
			{
				return CmdLeaderDim._FuncResultMode.FRM_TRUE;
			}
			if (ltf.isCheckedShareLeader)
			{
				int num = 1;
				for (;;)
				{
					Transaction transaction = new Transaction(this.m_doc, "AddItem");
					transaction.Start();
					try
					{
						XYZ end = this.m_uiDoc.Selection.PickPoint("请选择标记点");
						proportionText.AddLeader(0);
						RevitElementExtension.HyGetLeaders(proportionText).get_Item(num).End = end;
						RevitElementExtension.HyGetLeaders(proportionText).get_Item(num).Elbow = endPoint;
						transaction.Commit();
					}
					catch
					{
						transaction.Commit();
						break;
					}
					num++;
				}
			}
			else if (ltf.isMorePointShareLine)
			{
				int num2 = 1;
				for (;;)
				{
					Transaction transaction2 = new Transaction(this.m_doc, "AddItem");
					transaction2.Start();
					try
					{
						XYZ xyz = this.m_uiDoc.Selection.PickPoint("请选择标记点");
						XYZ end2 = Geometry.CalculateFootPoint(startPoint, endPoint, xyz);
						proportionText.AddLeader(0);
						RevitElementExtension.HyGetLeaders(proportionText).get_Item(num2).Elbow = endPoint;
						RevitElementExtension.HyGetLeaders(proportionText).get_Item(num2).End = end2;
						transaction2.Commit();
					}
					catch
					{
						transaction2.Commit();
						break;
					}
					num2++;
				}
			}
			return CmdLeaderDim._FuncResultMode.FRM_TRUE;
		}

		private void CalculatTextPosition(string strAlignStyle, double dTextWidth, double dOffsetY, XYZ ptSecond, XYZ ptThird, ref XYZ ptTextPos, ref SpecialCharactorDrawingKit.TextHorizontalAlignment hAlignment)
		{
			Autodesk.Revit.DB.View activeView = this.m_Revit.Application.ActiveUIDocument.ActiveView;
			XYZ upDirection = activeView.UpDirection;
			XYZ rightDirection = activeView.RightDirection;
			XYZ xyz = (ptThird - ptSecond).Normalize();
			if (strAlignStyle == "末端对齐")
			{
				ptTextPos = ptThird;
				if (xyz.IsAlmostEqualTo(rightDirection, 0.001))
				{
					hAlignment = SpecialCharactorDrawingKit.TextHorizontalAlignment.THA_RIGHT;
				}
				else
				{
					hAlignment = SpecialCharactorDrawingKit.TextHorizontalAlignment.THA_LEFT;
				}
			}
			else if (strAlignStyle == "居中对齐")
			{
				XYZ xyz2 = ptSecond + 0.5 * (ptThird - ptSecond);
				hAlignment = SpecialCharactorDrawingKit.TextHorizontalAlignment.THA_LEFT;
				if (xyz.IsAlmostEqualTo(rightDirection, 0.001))
				{
					ptTextPos = xyz2 - 0.5 * dTextWidth * xyz;
				}
				else
				{
					ptTextPos = xyz2 + 0.5 * dTextWidth * xyz;
				}
			}
			else
			{
				ptTextPos = ptSecond;
				if (xyz.IsAlmostEqualTo(rightDirection, 0.001))
				{
					hAlignment = SpecialCharactorDrawingKit.TextHorizontalAlignment.THA_LEFT;
				}
				else
				{
					hAlignment = SpecialCharactorDrawingKit.TextHorizontalAlignment.THA_RIGHT;
				}
			}
			ptTextPos += dOffsetY * upDirection;
		}

		private ExternalCommandData m_Revit;

        public static WindowHandle _hWndRevit;

		private enum _FuncResultMode
		{
			FRM_CONTINUE,
			FRM_TRUE,
			FRM_FALSE
		}
	}
}
